/*
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package l1j.server.server.model;

import static l1j.server.server.model.skill.L1SkillId.FIRE_WALL;

import java.lang.reflect.Constructor;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.opqlo.Server.L1World.L1World;
import l1j.server.server.IdFactory;
import l1j.server.server.datatables.NpcTable;
import l1j.server.server.datatables.SkillsTable;
import l1j.server.server.model.Instance.L1EffectInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.map.L1Map;
import l1j.server.server.model.map.L1WorldMap;
import l1j.server.server.serverpackets.S_DoActionGFX;
import l1j.server.server.serverpackets.S_NPCPack;
import l1j.server.server.templates.L1Npc;

// Referenced classes of package l1j.server.server.model:
// L1EffectSpawn

public class L1EffectSpawn {

	private static final Logger _log = Logger.getLogger(L1EffectSpawn.class.getName());

	private static L1EffectSpawn _instance;

	public static L1EffectSpawn getInstance() {
		if (_instance == null) {
			_instance = new L1EffectSpawn();
		}
		return _instance;
	}

	private Constructor<?> _constructor;

	private L1EffectSpawn() {
	}

	public void doSpawnFireRain(final L1Character cha ){
		final L1Npc firerain = NpcTable.getInstance().getTemplate(2000209);
		if (firerain == null) {
			throw new NullPointerException("FireWall data not found:npcid=2000209");
		}

		for(final Object obj : L1World.getInstance().getVisibleObjects(cha, 50)){
			 if(obj instanceof L1PcInstance){
				 boolean re = false;
				for(final L1Object object : L1World.getInstance().getVisibleObjects((L1PcInstance)obj, 0)){
					if(object instanceof L1EffectInstance){
						re = true;
					break;
					}
				}
				if(re){
					continue;
				}
				this.spawnEffect(2000209,20000,((L1Object) obj).getX(),((L1Object) obj).getY(),((L1Object) obj).getMapId(),null,0);
			}
		}
	}

	public void doSpawnFireWall(final L1Character cha, final int targetX, final int targetY) {
		final L1Npc firewall = NpcTable.getInstance().getTemplate(81157); // ファイアーウォール
		final int duration = SkillsTable.getInstance().getTemplate(FIRE_WALL).getBuffDuration();

		if (firewall == null) {
			throw new NullPointerException("FireWall data not found:npcid=81157");
		}

		L1Character base = cha;
		for (int i = 0; i < 8; i++) {
			final int a = base.targetDirection(targetX, targetY);
			int x = base.getX();
			int y = base.getY();
			if (a == 1) {
				x++;
				y--;
			} else if (a == 2) {
				x++;
			} else if (a == 3) {
				x++;
				y++;
			} else if (a == 4) {
				y++;
			} else if (a == 5) {
				x--;
				y++;
			} else if (a == 6) {
				x--;
			} else if (a == 7) {
				x--;
				y--;
			} else if (a == 0) {
				y--;
			}
			if (!base.isAttackPosition(x, y, 1)) {
				x = base.getX();
				y = base.getY();
			}
			final L1Map map = L1WorldMap.getInstance().getMap(cha.getMapId());
			if (!map.isArrowPassable(x, y, cha.getHeading())) {
				break;
			}

			final L1EffectInstance effect = this.spawnEffect(81157, duration * 1000, x, y,cha.getMapId(),(L1PcInstance)cha);
			if (effect == null) {
				break;
			}
			for (final L1Object objects : L1World.getInstance().getVisibleObjects(effect, 0)) {
				if (objects instanceof L1EffectInstance) {
					final L1EffectInstance npc = (L1EffectInstance) objects;
					if (npc.getNpcTemplate().get_npcId() == 81157) {
						npc.deleteMe();
					}
				}
			}
			if (targetX == x && targetY == y) {
				break;
			}
			base = effect;
		}

	}


	/**
	 * エフェクトオブジェクトを生成し設置する
	 *
	 * @param npcId
	 *            エフェクトNPCのテンプレートID
	 * @param time
	 *            存在時間(ms)
	 * @param locX
	 *            設置する座標X
	 * @param locY
	 *            設置する座標Y
	 * @param mapId
	 *            設置するマップのID
	 * @return 生成されたエフェクトオブジェクト
	 */
	public L1EffectInstance spawnEffect(final int npcId, final int time, final int locX,
			final int locY, final short mapId , final L1PcInstance user) {
		return this.spawnEffect(npcId, time, locX, locY, mapId, user, 0);
	}


	public L1EffectInstance spawnEffect(final int npcId, final int time, final int locX,
			final int locY, final short mapId, final L1PcInstance user, final int skiiId) {
		final L1Npc template = NpcTable.getInstance().getTemplate(npcId);
		L1EffectInstance effect = null;

		if (template == null) {
			return null;
		}

		final String className = new StringBuilder()
				.append("l1j.server.server.model.Instance.")
				.append(template.getImpl()).append("Instance").toString();

		try {
			this._constructor = Class.forName(className).getConstructors()[0];
			final Object obj[] = { template };
			effect = (L1EffectInstance) this._constructor.newInstance(obj);

			effect.setId(IdFactory.getInstance().nextId());
			effect.setGfxId(template.get_gfxid());
			effect.setX(locX);
			effect.setY(locY);
			effect.setHomeX(locX);
			effect.setHomeY(locY);
			effect.setHeading(0);
			effect.setMap(mapId);
			effect.setUser(user);
			effect.setSkillId(skiiId);
			L1World.getInstance().storeObject(effect);
			L1World.getInstance().addVisibleObject(effect);

			for (final L1PcInstance pc : L1World.getInstance().getRecognizePlayer(effect)) {
				effect.addKnownObject(pc);
				pc.addKnownObject(effect);
				pc.sendPackets(new S_NPCPack(effect));
				pc.broadcastPacketAll(new S_NPCPack(effect));
				//opqlo 流星雨陣
				if(effect.getNpcId() == 2000209){
					effect.broadcastPacketAll(new S_DoActionGFX(effect.getId(),0));
				}
				//opqlo 流星雨陣

			}
			final L1NpcDeleteTimer timer = new L1NpcDeleteTimer(effect, time);
			timer.begin();
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}

		return effect;
	}
}
